#pragma once
#include<iostream>
#include<unordered_map>
#include<vector>
#include<functional>
#include<errno.h>
#include<string.h>
#include<assert.h>
#include<stdint.h>
#include<sys/epoll.h>
#include"Channel.hpp"
#include"Log.hpp"

class EventLoop;
//Poller模块
#define MAX_EVENTS 1024 //最大事件数
//对epoll的封装
class Poller{
    private:
        int _epoll_fd; //epoll句柄
        struct epoll_event _events[MAX_EVENTS]; //事件数组(保存所有的活跃事件,用于系统调用epoll_wait与内核交互)
        std::unordered_map<int,Channel*> _channels; //channel映射表
    private:
        
        void EpollCtl(Channel *channel, int op)//对监听描述符进行事件控制
        {
            struct epoll_event event;
            event.data.fd = channel->Fd();
            event.events = channel->GetEvents();
            int ret = epoll_ctl(_epoll_fd, op, channel->Fd(), &event);
            if(ret < 0){
                LOG_ERR("epoll_ctl error");
                abort();
            }
        }
    public:
        Poller()
        { 
            _epoll_fd = epoll_create(1024); //创建epoll句柄
            if(_epoll_fd < 0){
                LOG_ERR("epoll_create error");
            }
            LOG_INF("Poller created : %d", _epoll_fd);
        }
        bool IsExistChannel(Channel *channel)//是否存在channel监听
        {
            // if(_channels.find(channel->Fd()) == _channels.end())
            //     return false;
            // return true;
            return _channels.find(channel->Fd()) != _channels.end();
        }
        void WaitEventsFromChannels(std::vector<Channel *> *active, int timeout = -1) //等待事件发生
        {
            int nfds = epoll_wait(_epoll_fd, _events, MAX_EVENTS, timeout); //等待事件发生
            if(nfds < 0){
                if(errno == EINTR)//如果是被信号中断，则忽略
                    return;
                else{
                    LOG_ERR("epoll_wait error : %s", strerror(errno));
                    abort();//如果是其他错误，则退出程序
                }
            }
            for(int i = 0;i<nfds;i++){
                auto it = _channels.find(_events[i].data.fd);
                assert(it!= _channels.end());
                it->second->SetRevents(_events[i].events);//设置就绪事件
                active->push_back(it->second); //将活跃channel添加到活跃列表中
            }
            // LOG_DBG("wait %d events sucess", nfds);
        }
        void AddChannel(Channel *channel)//添加监听描述符
        {
            if(IsExistChannel(channel)){
                return;
            }
            EpollCtl(channel, EPOLL_CTL_ADD);//添加监听描述符到内核
            _channels[channel->Fd()] = channel;//添加到channel映射表
            LOG_INF(" %d channel added to poller", channel->Fd());
        }
        void DelChannel(Channel *channel)//删除监听描述符
        {
            if(!IsExistChannel(channel))
                return;
            EpollCtl(channel, EPOLL_CTL_DEL);//从内核中删除监听描述符
            _channels.erase(channel->Fd());//从channel映射表中删除
        }
        void ModifChannel(Channel *channel)//修改监听描述符
        {
            if(!IsExistChannel(channel)){
                return;
            }
            EpollCtl(channel, EPOLL_CTL_MOD);//修改监听描述符的事件
        }
};


